package es.techideas.appsjam.model;

import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import es.techideas.appsjam.GameView;
import es.techideas.appsjam.R;

public class AbstractModelElement {

	public enum ContainerColor{ ORGANIC, VIDRE, PLASTICS, RESTA , PAPER , PUNT_VERD}

	private double x,y,height, width;

	private double velX,velY;

	protected Drawable image;

	protected GameView view;

	protected boolean selected;

	private int previousX;

	private int previousY;

	private Context context;

	private ContainerColor cc;

	protected Random rnd = new Random();


	public AbstractModelElement(Context context,GameView view, ContainerColor cc){
		this.context = context;
		this.view = view;
		this.cc = cc;
	}

	public ContainerColor getContainerColor() {
		return cc;
	}

	public void initialize(){
		image = context.getResources().getDrawable(getDrawableId());
		setWidth(image.getMinimumWidth());
		setHeight(image.getMinimumHeight());		
		initializePosition();
	}

	public void initializePosition() {
		setX(random(getWidth() / 2 , (view.getWidth()/2 - getWidth()/2)));
		setY(random(getHeight() / 2 , (view.getHeight() - getHeight() / 2)));
	}

	private double random(double min, double max) {
		double delta = max - min;
		double incremented = Math.random() * delta;
		return incremented + min;
	}

	public double getX() {
		return x;
	}

	public void setX(double x) {
		this.x = x;
	}

	public double getY() {
		return y;
	}

	public void setY(double y) {
		this.y = y;
	}

	public double getVelocityX() {
		return velX;
	}

	public void setVelocityX(double velX) {
		this.velX = velX;
	}

	public double getVelocityY() {
		return velY;
	}

	public void setVelocityY(double velY) {
		this.velY = velY;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public double getWidth() {
		return width;
	}

	public void setWidth(double width) {
		this.width = width;
	}

	public int getCanvasWidth(){
		return view.getWidth();
	}

	public int getCanvasHeight(){
		return view.getHeight();
	}

	protected static final double SLOW_DOWN_FACTOR = 15;

	public void updatePhysics(){
		long now = System.currentTimeMillis();
		double elapsed = getElapsedSeconds(now);
		if(!selected){

			x -= velX * elapsed / SLOW_DOWN_FACTOR;
			y -= velY * elapsed / SLOW_DOWN_FACTOR;

			if(getRight() > getCanvasWidth()){
				x = getCanvasWidth() - getWidth() / 2;
			}
			if(x < getWidth() / 2){
				x = getWidth() / 2;
			}
			if(y + getHeight() / 2 > getCanvasHeight()){
				y = getCanvasHeight() - getHeight() / 2;
			}
			if(y < getHeight() / 2 ){
				y = getHeight() / 2;
			}
		}
	}

	public void setSelected(boolean s){
		selected = s;
	}

	protected double getElapsedSeconds(long now) {
		return (double)((double) now - (double)view.getLastDrawTime())/1000;
	}

	public double getLeft(){
		return getX() - getWidth()/2;
	}

	public double getRight(){
		return getX() + getWidth()/2;
	}

	public double getTop(){
		return getY() - getHeight()/2;
	}

	public double getBottom(){
		return getY() + getHeight()/2;
	}

	public void draw(Canvas canvas){
		// Draw the ship with its current rotation
		canvas.save();

		previousX = (int) getX();
		previousY = (int) getY();

		// canvas.rotate((float) mHeading, (float) mX, mCanvasHeight - (float) mY);
		int left = (int)getLeft();
		int top = (int)getTop();
		int right = (int)getRight();
		int bottom = (int)getBottom();
		image.setBounds(left, top, right, bottom); 
		image.draw(canvas);
		canvas.restore();
	}

	public void touchDown(int x, int y) {
		if(hit(x,y)){
			setSelected(true);
			velX = 0;
			velY = 0;
		}
	}

	public void touchMove(int x, int y) {
		if(selected){
			setPositionUpdateVelocity(x,y);
		}
		else{
			touchDown(x, y);
		}		
	}

	private void setPositionUpdateVelocity(int x, int y) {
		long now = System.currentTimeMillis();
		if(view.getLastDrawTime() != 0){
			double elapsed = getElapsedSeconds(now);
			if(elapsed != 0){
				double deltaX = x - previousX;
				double deltaY = y - previousY;
				velX = -deltaX / elapsed;
				velY = -deltaY / elapsed;
			}
		}
		setX(x);
		setY(y);
	}

	public void touchUp() {
		setSelected(false);
	}

	public boolean hit(int x, int y) {
		if(x > getLeft() && x < getRight()){
			if(y > getTop() && y < getBottom()){
				return true;
			}
		}
		return false;
	}

	protected int getDrawableId() {
		switch(getContainerColor()){
		case VIDRE:
			return getRandomDrawableVidre();
		case PLASTICS:
			return getRandomDrawablePlastic();
		case RESTA:
			return getRandomDrawableResta();
		case PAPER:
			return getRandomDrawablePaper();
		case ORGANIC:
			return getRandomDrawableOrganic();
		default:
			return getRandomDrawablePuntVerd();
		}
	}

	private int getRandomDrawablePuntVerd() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.pv_0;
		case 1:
			return R.drawable.pv_1;
		case 2:
			return R.drawable.pv_2;
		case 3:
			return R.drawable.pv_3;			
		default:
			return R.drawable.pv_4;	
		}
	}

	private int getRandomDrawableOrganic() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.o_0;
		case 1:
			return R.drawable.o_1;
		case 2:
			return R.drawable.o_2;
		case 3:
			return R.drawable.o_3;			
		default:
			return R.drawable.o_4;	
		}
	}

	private int getRandomDrawablePaper() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.pc_0;
		case 1:
			return R.drawable.pc_1;
		case 2:
			return R.drawable.pc_2;
		case 3:
			return R.drawable.pc_3;			
		default:
			return R.drawable.pc_4;	
		}
	}

	private int getRandomDrawableResta() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.r_0;
		case 1:
			return R.drawable.r_1;
		case 2:
			return R.drawable.r_2;
		case 3:
			return R.drawable.r_3;			
		default:
			return R.drawable.r_4;	
		}
	}

	private int getRandomDrawablePlastic() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.p_0;
		case 1:
			return R.drawable.p_1;
		case 2:
			return R.drawable.p_2;
		case 3:
			return R.drawable.p_3;			
		default:
			return R.drawable.p_4;	
		}
	}

	private int getRandomDrawableVidre() {
		switch(rnd.nextInt(5)){
		case 0:
			return R.drawable.v_0;
		case 1:
			return R.drawable.v_1;
		case 2:
			return R.drawable.v_2;
		case 3:
			return R.drawable.v_3;			
		default:
			return R.drawable.v_4;	
		}
	}

	public GameView getView() {
		return view;
	}

	public int getCO2FingerPrint() {
		return 10;
	}

	public int getCO2Saving() {
		return 5;
	}

	public int getDespesaGestioImpropis() {
		return 3;
	}

	public int getEstalviEuros() {
		return 1;
	}
}
